import 'package:flutter/material.dart';
import '../widget/gradient_btn.dart';
import '../model/playing_card.dart';
import '../components/gesture_playingcard.dart';
import '../model/player.dart';

import '../blocs/room_bloc.dart';
import '../blocs/bloc_provider.dart';
import '../model/socket_msg.dart';
import '../static_var.dart';
import '../blocs/main_role_bloc.dart';
import './view_role.dart';
import '../model/ex_stream.dart';
import '../widget/loading_gradient_btn.dart';
import '../components/static_playingcard.dart';
import '../model/hand_cards.dart';

import '../model/cus_dialog.dart';
import '../user_proof.dart';

class ViewMainRole<T extends RoomBloc> extends StatefulWidget with ViewRole {
  final Color operateTextColor = StaticVar.yellowColor;

  ViewMainRole();

  Widget getAvatarWidget({String playerId, @required MainRoleBloc roleBloc}) {
    return getAvatar<MainRoleBloc>(playerId: UserProof.userId, roleBloc: roleBloc);
  }

  _ViewMainRoleDispose createState() {
    return _ViewMainRoleDispose<T>();
  }
}
class _ViewMainRoleDispose<T extends RoomBloc> extends State<ViewMainRole<T>> {
  RoomBloc bloc;
  List<String> waitCards = [];

  ExStream<bool> btnStreamPlayCards;
  LoadingGradientBtn playCardBtn;

  ExStream<bool> btnStreamPassCards;
  LoadingGradientBtn passCardBtn;

  List<String> otherRoleLastCards;

  final double btnWidth = 72;
  final double btnHeight = 26;
  final TextStyle operateBtnTextStyle = TextStyle(color: Colors.white);

  List cardsList;
  Map<String, Map<String, dynamic>> cardsMap = {};
  int lastTriggerIndex;

  String cardsStackKeyPrefix;
  int maxCardsCount;

  int get cardsCount => null == this.cardsList ? null : this.cardsList.length;
  
  @override
  void initState() {
    super.initState();
  }

  Widget getOperateText(String text) {
    return Text(text, style: TextStyle(color: widget.operateTextColor, fontWeight: FontWeight.w600, fontSize: 15));
  }
  Widget getLastCards(List cardTexts) {
    double divideDis = 13;
    double cardsWidgetsWidth = divideDis * (cardTexts.length - 1) + PlayingCard.cardWidth2;
    double startPosLeft = 0;

    List<Widget> cardWidgets = [];
    cardTexts.forEach((cardText){
      cardWidgets.add(Positioned(
        left: startPosLeft,
        child: StaticPlayingCard(PlayingCard(cardText: cardText,sizeType: 2)),
      ));
      startPosLeft += divideDis;
    });
    return Container(
      alignment: Alignment.center,
      child: Container(
        width: cardsWidgetsWidth,
        height: PlayingCard.cardHeight2,
        padding: EdgeInsets.only(bottom: 6),
        child: Stack(
          overflow: Overflow.visible,
          children: cardWidgets,
        )
      )
    );
  }
  Widget getOperateBtns() {
    return StreamBuilder<Map>(
      stream: bloc.mainRoleBloc.statusStream,
      initialData: bloc.mainRoleBloc.statusData,
      builder: (BuildContext context, AsyncSnapshot<Map> snapshot) {
        List<Widget> widgets = [];
        PlayerStatus status = snapshot.data['status'];
        switch (status) {
          case PlayerStatus.notReady:
            widgets.add(GradientBtn(width: btnWidth, height: btnHeight, child: Text('准备', style: operateBtnTextStyle), pressed: (){
              bloc.sendReadyMsg();
            }));
            break;
          case PlayerStatus.ready:
            widgets.add(GradientBtn(width:btnWidth, height: btnHeight, child: Text('取消准备', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.cancelReady);
            }));
            break;
          case PlayerStatus.getCard:
            widgets.add(Container());
            break;
          case PlayerStatus.isCallLandlord:
            widgets.add(GradientBtn(width: btnWidth, colorType: 2, height: btnHeight, child: Text('不叫', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.notLandlord);
            }));
            widgets.add(Container(width: 10));
            widgets.add(GradientBtn(width: btnWidth, height: btnHeight, child: Text('叫地主', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.callLandlord);
            }));
            break;
          case PlayerStatus.callLandlord:
            widgets.add(getOperateText('叫地主'));
            break;
          case PlayerStatus.notLandlord:
            widgets.add(getOperateText('不叫'));
            break;
          case PlayerStatus.isRobLandlord:
            widgets.add(GradientBtn(width: btnWidth, colorType: 2, height: btnHeight, child: Text('不抢', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.notRobLandlord);
            }));
            widgets.add(Container(width: 10));
            widgets.add(GradientBtn(width: btnWidth, height: btnHeight, child: Text('抢地主', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.robLandlord);
            }));
            break;
          case PlayerStatus.robLandlord:
            widgets.add(getOperateText('抢地主'));
            break;
          case PlayerStatus.notRobLandlord:
            widgets.add(getOperateText('不抢'));
            break;
          case PlayerStatus.isRestart:
            widgets.add(
              GradientBtn(
                width: 80,
                height: 25,
                colorType: 2,
                child: Text('离开', style: TextStyle(color: Colors.white)),
                pressed: (){
                  this.bloc.sendOutRoom();
                  Navigator.of(context).pushReplacementNamed('/lobby');
                },
              )
            );
            widgets.add(Container(width: 10));
            widgets.add(
              GradientBtn(
                width: 100,
                height: 25,
                child: Text('继续游戏', style: TextStyle(color: Colors.white)),
                pressed: (){
                  this.bloc.goonGame();
                },
              )
            );
            break;
          case PlayerStatus.firstHand:
            widgets.add(GradientBtn(width: btnWidth, height: btnHeight, child: Text('明牌', style: operateBtnTextStyle), pressed: () {
              bloc.sendMsg(type: SendMsgType.openHand);
            }));
            widgets.add(Container(width: 10));
            widgets.add(GradientBtn(width: btnWidth, height: btnHeight, child: Text('出牌', style: operateBtnTextStyle), pressed: () {}));
            break;
          case PlayerStatus.thinking:
            this.otherRoleLastCards = snapshot.data['otherRoleLastCards'];
            
            if(null != this.otherRoleLastCards) {
              if(null == passCardBtn) {
                btnStreamPassCards = ExStream<bool>.broadcast(false);
                passCardBtn = LoadingGradientBtn(width: btnWidth, height: btnHeight, colorType: 2, child: Text('不出', style: operateBtnTextStyle), pressed: () {
                  btnStreamPassCards.setData(true);
                  bloc.passCards();
                }, exStream: btnStreamPassCards, closeStreamInDispose: false);
              }
              widgets.add(passCardBtn);
              widgets.add(Container(width: 10));
            }
            if(null == playCardBtn) {
              btnStreamPlayCards = ExStream<bool>.broadcast(false);
              playCardBtn = LoadingGradientBtn(width: btnWidth, height: btnHeight, child: Text('出牌', style: operateBtnTextStyle), pressed: () {
                if(this.waitCards.length > 0) {
                  HandCards handCards = HandCards(cardsText: this.waitCards);
                  if(handCards.cardsType == CardsType.illegal || (null != this.otherRoleLastCards && handCards.compareTo(HandCards(cardsText: this.otherRoleLastCards))< 1)) {
                    CusDialog.alert(context: context, content: '出牌不符合规则', type: DialogType.error);
                    return;
                  }
                  
                  btnStreamPlayCards.setData(true);
                  bloc.playCards(cards: handCards.toRightList(), cardsType: handCards.cardsType);
                  this.waitCards = [];
                }
              }, exStream: btnStreamPlayCards, closeStreamInDispose: false);
            }
            widgets.add(playCardBtn);
            break;
          case PlayerStatus.waiting:
            if(null != btnStreamPlayCards) {
              btnStreamPlayCards.setData(false);
            }
            if(null != btnStreamPassCards) {
              btnStreamPassCards.setData(false);
            }
            List lastCards = snapshot.data['lastCards'];
            if(lastCards != null && lastCards.length > 0) {
              widgets.add(getLastCards(lastCards));
            }else if(null != btnStreamPlayCards){
              widgets.add(getOperateText('不要'));
            }
            break;
          default: 
            break;
        }
        return Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: widgets
        );
      }
    );
  }
  void triggerCardWait({double dx, double divideDis, bool isUpdateOpe}) {
    int index = dx ~/ divideDis;
    
    if(index == cardsCount) {
      double offset = dx - divideDis * (cardsCount - 1);
      if(offset > 0 && offset <= PlayingCard.cardWidth) {
        index = cardsCount - 1;
      }
    }
    if(index >= cardsCount) {
      return;
    }

    if((isUpdateOpe && this.lastTriggerIndex == index) || index >= this.cardsCount || index < 0) {
      return;
    }
    this.lastTriggerIndex = index;
    String cardText = this.cardsList[index];
    Map<String, dynamic> cardData = this.cardsMap[cardText];
    if(null != cardData) {
      ExStream currentStream = cardData['stream'];
      bool isWait = currentStream.data;
      if(isWait) {
        this.waitCards.remove(cardText);
        currentStream.setData(false);
      }else {
        if(this.waitCards.indexOf(cardText) == -1) {
          this.waitCards.add(cardText);
        }
        currentStream.setData(true);
      }
    }
  }
  Widget getCardsStack() {
    return StreamBuilder<Map>(
      stream: bloc.mainRoleBloc.signStream,
      initialData: bloc.mainRoleBloc.signData,
      builder: (BuildContext context, AsyncSnapshot<Map> snapshotIsLandlord) {
        bool roleIsLandlord = snapshotIsLandlord.data['isLandlord'];
        this.cardsMap = {};
        this.maxCardsCount = snapshotIsLandlord.data['maxCountCards'];
        return StreamBuilder<List>(
          stream: bloc.mainRoleBloc.cardsStreamStream,
          initialData: bloc.mainRoleBloc.cardsData,
          builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
            List<Widget> stackchildren = [];
            double positionLeft = 0;
            List cards = snapshot.data;
            if(null == this.cardsList || this.maxCardsCount == this.cardsCount) {
              cardsStackKeyPrefix = DateTime.now().toString();
            }
            this.cardsList = cards;

            double divideDis = 25;
            double cardsWidgetsWidth = divideDis * (cards.length - 1) + PlayingCard.cardWidth;
            cards.forEach((cardText){
              if(!this.cardsMap.containsKey(cardText)) {
                this.cardsMap[cardText] = {'stream': ExStream.broadcast(false)};
                this.cardsMap[cardText]['widget'] = GesturePlayingCard(card: PlayingCard(cardText: cardText, isLandLord: roleIsLandlord), triggerWaitStream: this.cardsMap[cardText]['stream']);
              }
              stackchildren.add(Positioned(
                key: Key(cardsStackKeyPrefix + cardText), //强制刷新
                left: positionLeft,
                child: this.cardsMap[cardText]['widget']
              ));
              positionLeft += divideDis;
            });
            return Container(
              alignment: Alignment.center,
              child: Container(
                height: PlayingCard.cardHeight,
                width: cardsWidgetsWidth,
                child: Builder(
                  builder: (BuildContext context1) {
                    return GestureDetector(
                      onHorizontalDragUpdate: (detail){
                        RenderBox box = context1.findRenderObject();
                        double detailX = box.globalToLocal(detail.globalPosition).dx;
                        triggerCardWait(dx: detailX, divideDis: divideDis, isUpdateOpe: true);
                      },
                      onPanDown: (detail) {
                        RenderBox box = context1.findRenderObject();
                        double detailX = box.globalToLocal(detail.globalPosition).dx;
                        triggerCardWait(dx: detailX, divideDis: divideDis, isUpdateOpe: false);
                      },
                      child: Stack(
                        overflow: Overflow.visible,
                        children: stackchildren
                      )
                    );
                  },
                )
              ),
            );
          }
        );
      }
    );
  }
  @override
  Widget build(BuildContext context) {
    this.bloc = BlocProvider.of<T>(context);
    return Container(
      margin: EdgeInsets.symmetric(vertical: 10),
      child: Row(
        children: <Widget>[
          widget.getAvatarWidget(playerId: UserProof.userId, roleBloc: this.bloc.mainRoleBloc),
          Expanded(
            child: Column(
              children: <Widget>[
                Container(
                  height: PlayingCard.cardHeight2 + 6,
                  padding: EdgeInsets.only(bottom: 8),
                  child: getOperateBtns(),
                ),
                getCardsStack()
              ]
            )
          )
        ],
      )
    );
  }

  @override
  void dispose() {
    cardsMap.values.forEach((item){
      (item['stream'] as ExStream).dispose();
    });
    
    super.dispose();
  }
}